/**
 * 
 */
package com.ms.service.module.baccarat;

import java.util.ArrayList;

import com.ms.service.module.baccarat.bin.BacrBetType;
import com.xpec.c4.game.system.InitData;
import com.xpec.c4.game.utility.GUIDFactory;
import com.xpec.c4.game.utility.GameUtility;
import com.xpec.c4.message.ConstantCode;

/**
 * 計算歷史資訊趨勢
 * 
 * @author TW15010
 */
public class BacrHistoryTrendParser {
	/**
	 * 勝方 combo 資訊
	 * 
	 * @author TW15010
	 */
	private class ComboInfo {
		public int winType;
		public int comboLength;

		@Override
		public String toString() {
			return winType + "," + comboLength;
		}
	}

	// 基本參數 ========================================

	/**
	 * 當前莊閒 {@link BacrBetType}
	 */
	private int curWinnerType;

	/**
	 * 當前莊閒連局數<br>
	 * 上一次切換贏家到目前的連勝鋪數<br>
	 * 目前贏家的連勝鋪數
	 */
	private int curWinnerComboLength;

	/**
	 * 定長連閒長度<br>
	 * 目前贏家的連勝鋪數, 閒家第一組 combo 長度
	 */
	private int playerFirstComboLength;

	/**
	 * 定長連閒次數<br>
	 * 目前贏家的連勝鋪數, 與閒家第一組 combo 同樣長度的重複次數
	 */
	private int playerFirstComboLoopCount;

	/**
	 * 定長連莊長度<br>
	 * 目前贏家的連勝鋪數, 莊家第一組 combo 長度
	 */
	private int bankerFirstComboLength;

	/**
	 * 定長連莊次數<br>
	 * 目前贏家的連勝鋪數, 與莊家第一組 combo 同樣長度的重複次數
	 */
	private int bankerFirstComboLoopCount;

	// 分析結果 ===========================================

	/**
	 * 趨勢值
	 */
	private int trendValue;

	/**
	 * 押注類型 {@link BacrBetType}
	 */
	private int betType;

	/**
	 * 畫出簡易珠路
	 */
	public static String getHistoryLineText(ArrayList<BacrGameResult> resultList) {
		StringBuilder sb = new StringBuilder();
		StringBuilder fullResultListSb = new StringBuilder();
		StringBuilder outputSb = new StringBuilder();

		int length = resultList.size();
		if (length == 0) {
			return "";
		}

		int comboSectionCnt = 1;
		int lastComboType = resultList.get(0).getWinnerType();

		sb.append(comboSectionCnt + ". ");
		for (BacrGameResult result : resultList) {
			fullResultListSb.append(result.getWinTypeChar());

			int winType = result.getWinnerType();
			if (winType == lastComboType) {
				sb.append(result.getWinTypeChar());
			} else {
				comboSectionCnt++;
				sb.append("\n");
				sb.append(comboSectionCnt + ". ");
				sb.append(result.getWinTypeChar());
				lastComboType = winType;
			}
		}

		outputSb.append("===============\n");
		outputSb.append(fullResultListSb);
		outputSb.append("\n===============\n");
		outputSb.append(sb);
		outputSb.append("\n===============");

		return outputSb.toString();
	}

	/**
	 * 取得分析結果字串
	 * 
	 * @return
	 */
	public String getResultText() {
		StringBuilder sb = new StringBuilder();

		sb.append("\ntrend = " + getTrendValue());
		sb.append("\ntype = " + ConstantCode.getName(BacrBetType.class, getBetType()));
		sb.append("\nCurWinnerType = " + ConstantCode.getName(BacrBetType.class, getCurWinnerType()));
		sb.append("\nCurWinnerComboLength = " + getCurWinnerComboLength());
		sb.append("\nPlayerFirstComboLength = " + getPlayerFirstComboLength());
		sb.append("\nPlayerFirstComboLoopCount = " + getPlayerFirstComboLoopCount());
		sb.append("\nBankerFirstComboLength = " + getBankerFirstComboLength());
		sb.append("\nBankerFirstComboLoopCount = " + getBankerFirstComboLoopCount());

		return sb.toString();
	}

	/**
	 * 排除和局, 整理出所有勝方 combo 列表
	 * 
	 * @param resultList
	 * @return
	 */
	private ArrayList<ComboInfo> convertToComboList(ArrayList<BacrGameResult> resultList) {
		// 記錄 combo 類型和次數的列表
		ArrayList<ComboInfo> comboList = new ArrayList<ComboInfo>();

		// 最後 combo 的勝方類型
		int lastComboType = -1;

		// 目前的 combo 長度
		int curComboLength = 1;

		// 對勝負列表的 index
		int idx = -1;

		// 掃一遍所有結果, 排除和局, 整理出勝方 combo 列表
		for (BacrGameResult result : resultList) {
			idx++;

			int winType = result.getWinnerType();

			// 到達 combo type 切換的地方
			if (winType != lastComboType) {
				// 跳過第一局的結果才開始計算, 否則會取不到最後一次勝方類型
				if (idx > 0) {
					// 排除和局
					if (lastComboType != BacrBetType.TIE) {
						// 加到 combo 列表
						ComboInfo ci = new ComboInfo();
						ci.winType = lastComboType;
						ci.comboLength = curComboLength;
						comboList.add(ci);
					}
				} // if (idx > 0) {

				lastComboType = winType;
				curComboLength = 1;
			} else { // if (winType != lastComboType) { else
				curComboLength++;
			} // if (winType != lastComboType) {
		} // for (BacrGameResult result : resultList) {

		// 把最後一組補進去
		if (idx >= 0) {
			if (lastComboType != BacrBetType.TIE) {
				ComboInfo ci = new ComboInfo();
				ci.winType = lastComboType;
				ci.comboLength = curComboLength;
				comboList.add(ci);
			}
		}

		return comboList;
	}

	/**
	 * 從 combo 列表中統計出基本參數
	 * 
	 * @param comboList
	 */
	private void parseBasicParam(ArrayList<ComboInfo> comboList) {
		// 跟莊閒第一組 combo 同樣長度的 combo 是否已經中斷
		boolean bankerSameLenComboBreak = false;
		boolean playerSameLenComboBreak = false;

		// 倒著掃一遍 combo 列表
		int max = comboList.size();
		int firstDataIdx = max - 1;
		for (int idx = firstDataIdx; idx >= 0; idx--) {
			ComboInfo ci = comboList.get(idx);
			boolean firstData = (idx == firstDataIdx);

			if (firstData) {
				// 目前的勝方與連勝 combo 長度
				curWinnerType = ci.winType;
				curWinnerComboLength = ci.comboLength;
			} else {
				switch (ci.winType) {
				case BacrBetType.PLAYER:
					// 閒家的第一組 combo 長度
					if (playerFirstComboLength == 0) {
						playerFirstComboLength = ci.comboLength;
					}

					// 目前的 combo 長度與上次的不同，combo 中斷
					if (ci.comboLength != playerFirstComboLength) {
						playerSameLenComboBreak = true;
					}

					// combo 沒中斷就繼續累加次數
					if (!playerSameLenComboBreak) {
						playerFirstComboLoopCount++;
					}
					break;
				case BacrBetType.BANKER:
					// 莊家的第一組 combo 長度
					if (bankerFirstComboLength == 0) {
						bankerFirstComboLength = ci.comboLength;
					}

					// 目前的 combo 長度與上次的不同，combo 中斷
					if (ci.comboLength != bankerFirstComboLength) {
						bankerSameLenComboBreak = true;
					}

					// combo 沒中斷就繼續累加次數
					if (!bankerSameLenComboBreak) {
						bankerFirstComboLoopCount++;
					}
					break;
				} // switch (ci.winType) {
			}
		} // for (ComboInfo ci : comboList) {
	}

	/**
	 * 分析
	 * 
	 * @param resultList
	 */
	public boolean parse(ArrayList<BacrGameResult> resultList) {
		if (GameUtility.getArrayListSize(resultList) == 0) {
			return false;
		}

		// 記錄 combo 類型和次數的列表
		ArrayList<ComboInfo> comboList = convertToComboList(resultList);
		if (GameUtility.getArrayListSize(comboList) == 0) {
			return false;
		}

		// 從 combo 列表中統計出基本參數
		parseBasicParam(comboList);

		int firstComboLength = 0;
		int firstComboLoopCount = 0;
		int reverseWinType = 0;

		// 分析押注目標和趨勢值
		switch (curWinnerType) {
		case BacrBetType.PLAYER:
			firstComboLength = playerFirstComboLength;
			firstComboLoopCount = playerFirstComboLoopCount;
			reverseWinType = BacrBetType.BANKER;
			break;
		case BacrBetType.BANKER:
			firstComboLength = bankerFirstComboLength;
			firstComboLoopCount = bankerFirstComboLoopCount;
			reverseWinType = BacrBetType.PLAYER;
			break;
		}

		if (curWinnerComboLength > firstComboLength) {
			trendValue = curWinnerComboLength;
			betType = curWinnerType;
		} else {
			trendValue = firstComboLoopCount;

			if (curWinnerComboLength == firstComboLength) {
				betType = reverseWinType;
			} else {
				betType = curWinnerType;
			}
		}

		return true;
	}

	public int getCurWinnerType() {
		return curWinnerType;
	}

	public int getCurWinnerComboLength() {
		return curWinnerComboLength;
	}

	public int getPlayerFirstComboLength() {
		return playerFirstComboLength;
	}

	public int getPlayerFirstComboLoopCount() {
		return playerFirstComboLoopCount;
	}

	public int getBankerFirstComboLength() {
		return bankerFirstComboLength;
	}

	public int getBankerFirstComboLoopCount() {
		return bankerFirstComboLoopCount;
	}

	public int getTrendValue() {
		return trendValue;
	}

	public int getBetType() {
		return betType;
	}

	/**
	 * 測試用
	 * 
	 * @param args
	 */
	public static void main(String[] args) {
		InitData.initAll();

		GUIDFactory.setProcessId(1);
		GUIDFactory.setWorldId(1);

		ArrayList<BacrGameResult> resultList = new ArrayList<BacrGameResult>();

		String resultStr = "BPBBPBBPTPBBPPPTBPBPPBPPBBBPPBPBPPTBTBBBPPBBPBBBBTBTPPPPP";
		for (char c : resultStr.toCharArray()) {
			String chr = String.valueOf(c);
			chr = chr.toUpperCase();

			if (chr.equals("B")) {
				resultList.add(new BacrGameResult((byte) BacrBetType.BANKER, false, false));
			} else if (chr.equals("P")) {
				resultList.add(new BacrGameResult((byte) BacrBetType.PLAYER, false, false));
			} else if (chr.equals("T")) {
				resultList.add(new BacrGameResult((byte) BacrBetType.TIE, false, false));
			}
		}

		BacrHistoryTrendParser p = new BacrHistoryTrendParser();
		System.out.println(BacrHistoryTrendParser.getHistoryLineText(resultList));
		p.parse(resultList);
		System.out.println(p.getResultText());
	}
}
